package cn.crex1.xiaomi.util;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map.Entry;

public class PagesUtil<E> implements Serializable {

	private static final long serialVersionUID = 1L;

	private static Logger logger = LoggerFactory.getLogger(PagesUtil.class);

	private Integer firstPage;// 第一页

	private Integer lastPage;// 尾页

	private Integer totalPage;// 总页数

	private Integer lastPageDataCount;// 除不尽时 最后一页数据数

	private Integer perPageDataCount;// 每页显示数据数

	private Map<Integer, List<E>> perPageData = new ConcurrentHashMap<>();// 每页数据

	public PagesUtil() {
	}

	public PagesUtil(List<E> data, Integer perPageDataCount) {
		this.perPageDataCount = perPageDataCount;
		initPages(data);
		initFirstAndLastpage();
		initPageDatas(data);
	}

	/**
	 * 根据传入的数据 和 每页显示数据数 确定分页
	 * 
	 * @param <E>
	 * @param data
	 * @param perPageData
	 * @return
	 */
	public static <E> PagesUtil createPagesByDatas(List<E> data, Integer perPageDataCount) {
		return new PagesUtil<E>(data, perPageDataCount);
	}

	/**
	 * 初始化页数
	 * 
	 * @param data
	 * @param perPageData
	 */
	private void initPages(List<E> data) {
		// 分页数据小于每页显示数据
		if (data.size() < perPageDataCount) {
			totalPage = 1;
			lastPageDataCount = data.size();
			perPageDataCount = data.size();
		}
		// 总数据数与每页显示数据相等 只有一页
		if (data.size() == perPageDataCount) {
			totalPage = 1;
			lastPageDataCount = perPageDataCount;
		}
		// 总页数 整除
		else if (data.size() % perPageDataCount == 0) {
			totalPage = data.size() / perPageDataCount;
			lastPageDataCount = perPageDataCount;
			// 不能整除
		} else {
			totalPage = (data.size() / perPageDataCount) + 1;
			lastPageDataCount = data.size() - (perPageDataCount * (totalPage - 1));
		}
	}

	/**
	 * 初始化 首页码 和 尾页码
	 */
	private void initFirstAndLastpage() {
		this.firstPage = 1;
		this.lastPage = this.totalPage;
	}

	private void initPageDatas(List<E> data) {
		// 每页 开始索引 对应集合中的位置
		Integer perPageStartIndex = 0;
		for (int i = 0; i < totalPage; i++) {
			List<E> perPageLists = new ArrayList<>();
			for (int j = 0; j < perPageDataCount; j++) {
				perPageLists.add(data.get(j + perPageStartIndex));
				//总页数大于1 
				if (totalPage > 1) {
					// 计算每页开始索引
					if ((perPageDataCount - 1) == j) {
						perPageStartIndex = j + perPageStartIndex + 1;
					}
					// 重置每页开始索引
					if (data.size() == j + perPageStartIndex) {
						perPageStartIndex = 0;
					}
					// 取出最后一页数据
					if (data.size() == perPageStartIndex + lastPageDataCount) {
						perPageDataCount = lastPageDataCount;
					}
				}
			}
			// 每页数据放入数组
			perPageData.put(i + 1, perPageLists);
		}
		logger.debug("firstPage: " + firstPage + ", lastPage: " + lastPage + ", totalPage: " + totalPage);
	}

	/**
	 * 分页数据缓存 根据每页显示数据数
	 * 
	 * @param cplist
	 * @param perPageDataCount
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static <E> PagesUtil pageDatasCache(List<E> cplist, Integer perPageDataCount) {

		// 创建分页数据
		PagesUtil<E> pages = PagesUtil.createPagesByDatas(cplist, perPageDataCount);
		// 遍历
		Set<Entry<Integer, List<E>>> set = pages.getPerPageData().entrySet();
		// 放入缓存
		for (Entry<Integer, List<E>> entry : set) {
			RedisUtil.Lists.lpush(JsonUtils.writeStringByObject(entry.getKey()), JsonUtils.writeStringByObject(entry.getValue()));
			RedisUtil.Keys.expired(JsonUtils.writeStringByObject(entry.getKey()), 180);
		}
		return pages;
	}

	/**
	 * 
	 * @return
	 */
	public Map<Integer, List<E>> getPerPageData() {
		return perPageData;
	}

	public Integer getFirstPage() {
		return firstPage;
	}

	public Integer getLastPage() {
		return lastPage;
	}

	public Integer getTotalPage() {
		return totalPage;
	}
}
